#pragma once
#include "Log.hpp"
#include <sstream>

namespace my_cloud {
    namespace fs = std::experimental::filesystem;
    class FileUtil {
    private:
        std::string _filename;
    public:
        FileUtil(const std::string& filename) : _filename(filename) {}
        size_t FileSize() {
            struct stat st;
            if (stat(_filename.c_str(), &st) == -1) {
                LOG(WARING, "FileSize Error!");
                return 0;
            }
            return st.st_size;
        }
        time_t FileMTime() {
            struct stat st;
            if (stat(_filename.c_str(), &st) == -1) {
                LOG(WARING, "FileMTime Error!");
                return 0;
            }
            return st.st_mtime;
        }
        time_t FileATime() {
            struct stat st;
            if (stat(_filename.c_str(), &st) == -1) {
                LOG(WARING, "FileATime Error!");
                return 0;
            }
            return st.st_atime;
        }
        std::string FileName() {
            int pos = _filename.rfind("\\");
            if (pos == std::string::npos) {
                return _filename;
            }
            return _filename.substr(pos + 1);
        }
        bool GetPosLen(std::string& content, size_t pos, size_t len) {
            if (pos + len > FileSize()) {
                LOG(WARING, "GetPosLen Error!");
                return false;
            }
            std::ifstream ifs(_filename, std::ios::binary);
            if (ifs.is_open() == false) {
                LOG(WARING, "Open " + _filename + " Error!");
                return false;
            }
            content.resize(len);
            ifs.seekg(pos, std::ios::beg);
            ifs.read(&content[0], len);
            if (ifs.good() == false) {
                LOG(WARING, "GetPosLen Error!");
                return false;
            }
            ifs.close();
            return true;
        }
        bool GetContent(std::string& content) {
            if (GetPosLen(content, 0, FileSize()) == false) {
                LOG(WARING, "GetContent Error!");
                return false;
            }
            return true;
        }
        bool SetContent(const std::string& content) {
            //std::ofstream ofs(_filename, std::ios::binary | std::ios::trunc);
            std::ofstream ofs(_filename, std::ios::binary);

            if (ofs.is_open() == false) {
                LOG(WARING, "Open : " + _filename + " Error!");
                return false;
            }
            ofs.write(content.c_str(), content.size());
            if (ofs.good() == false) {
                LOG(WARING, "SetContent ERROR!");
                return false;
            }
            ofs.close();
            return true;
        }
        bool Exists() {
            return fs::exists(_filename);
        }
        bool Remove() {
            if (Exists() == false) {
                return true;
            }
            remove(_filename.c_str());
            return true;
        }
        bool CreateDir() {
            if (Exists() == true) {
                return true;
            }
            return fs::create_directories(_filename);
        }
        bool ScanDir(std::vector<std::string>& arry) {
            for (auto& p : fs::directory_iterator(_filename)) {
                if (fs::is_directory(p) == true) {
                    continue;
                }
                arry.push_back(fs::path(p).relative_path().string());
            }
            return true;
        }
    };
}
